/*
 * UserLoginModule.java
 *
 * Created on 4 Ноябрь 2006 г., 16:12
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package server.authentification.module;

import com.persistent.entity.Authentification;
import com.persistent.model.AbstractFacade;
import com.persistent.model.facade.AuthentificationFacade;
import com.sun.corba.se.spi.activation.Server;
import java.util.*;
import java.sql.*;
import java.util.logging.Level;
import javax.persistence.EntityManager;
import javax.transaction.UserTransaction;
import org.apache.log4j.Logger;
import static server.authentification.module.crypto.GetPassword.setHash;
import static server.authentification.module.crypto.UserPasswordCheck.auth;
import javax.naming.*;
import javax.security.auth.spi.LoginModule;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;

import javax.sql.*;
import server.utils.Chat;

/**
 * JAAS LoginModule configure string in {$HOME}/jre/bin/security/java.security
 */
public class UserLoginModule implements LoginModule {
    CallbackHandler handler;
    Subject subject;
    Map sharedState;
    Map options;
    
    /**
     *  Class Logger
     */
    private static Logger log;
    
    /**
     * login flag
     */
    private boolean loginPassed = false;
    
    public UserLoginModule() {}
    
    /**
     *
     * @param subject
     * @param handler
     * @param sharedState
     * @param options
     */
    public void initialize(Subject subject, CallbackHandler handler,
            Map sharedState, Map options) {
        this.handler = handler;
        this.options = options;
        this.sharedState = sharedState;
        this.subject = subject;
        log = Logger.getLogger(server.authentification.module.UserLoginModule.class);
        log.info("++Authenificate Start");
    }
    
    /**
     * Login method starts when configure ends
     * @throws javax.security.auth.login.LoginException
     * @return login or not login?This is the question.
     */
    public boolean login() throws LoginException {
        String name = "";
        String pass = "";
        
        boolean passed = false;
        try {
            
            Callback[] callbacks = new Callback[2];
            callbacks[0] = new NameCallback("Username:");
            callbacks[1] = new PasswordCallback("Password:", false);
            //
            Chat.write("dshdfhdfhdfhdfhdfhdfhdfh");
            String read = Chat.read();
            handler.handle(callbacks);
            //gets name and password
            NameCallback namec = (NameCallback) callbacks[0];
            name = namec.getName();
            
            PasswordCallback passc = (PasswordCallback) callbacks[1];
            pass = new String(passc.getPassword());
            
            String seed =new String(new Double(Math.random()).toString());
            String hash = setHash(name,pass,seed);
            
            //TODO : Use Authentificator?????
            AuthentificationFacade facade = new AuthentificationFacade();
            Authentification auth = facade.findByUsername(name);
            if (auth!=null) {
                String basehash = auth.getPassword();
                if(!auth(hash,name,seed,basehash)){
                    throw new FailedLoginException("The password is incorrect");
                }else {
                    loginPassed = true;
                    return true;
                }
            } else {
                loginPassed = false;
                throw new FailedLoginException("The username is incorrect");
            }
        } catch (Exception e) {
            throw new LoginException(e.getMessage());
        }
    }
    
    /**
     * after authentification
     */
    public boolean commit() throws LoginException {
        return loginPassed;
    }
    
    public boolean abort() throws LoginException {
        boolean bool = loginPassed;
        loginPassed = false;
        return bool;
    }
    
    public boolean logout() throws LoginException {
        loginPassed = false;
        return true;
    }
}

